<?php

namespace App\Http\Controllers\Web\Prize;

use App\App\Services\PrizeService as PrizeAppService;
use App\App\Services\PrizeStockService;
use App\App\Services\StorageService;
use App\App\Services\Web\UserService;
use App\Events\EntityPrizeCreated;
use App\Http\Controllers\Controller;
use App\Models\ActivityPrize\ActivityPrizeService;
use App\Models\Prize\Prize;
use App\Models\Prize\PrizeService as PrizeModelService;
use App\Models\PrizePayment\PrizePaymentService;
use App\Models\PrizeRecord\PrizeRecordService;
use App\Models\PrizeType\PrizeType;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;

class PrizeController extends Controller
{
    /**
     * 奖品列表页数据接口
     * @param PrizeStockService $prizeStockService
     * @param Request $request
     * @param PrizeAppService $prizeAppService
     * @param PrizeModelService $prizeModelService
     * @return \Illuminate\Http\JsonResponse
     */
    public function query(PrizeStockService $prizeStockService, Request $request, PrizeAppService $prizeAppService, PrizeModelService $prizeModelService)
    {
        $this->validate($request, [
            'name'     => 'string|nullable',
            'resource' => 'integer|nullable',
            'limit'    => 'integer|nullable',
            'offset'   => 'integer|nullable',
        ]);
        $requestData['name'] = $request->get('name');
        $requestData['resource'] = $request->get('resource');
        $conditions = $prizeAppService->prepareQueryConditiond($requestData);
        $limit = $request->get('limit', 10);
        $offset = $request->get('offset', 0);
        $prizeInfos = $prizeModelService->getPrizeByConditions($conditions,
            ['prizeType', 'sponsor', 'activity', 'prizeRecord', 'prizePayment'], $limit, $offset);
        $prizeInfoArray = $prizeInfos->toArray();
        $showPrizeInfos = $prizeAppService->analyzePrizeInfo($prizeInfoArray);

//        return view('web.prize.listPrize',
//            [
//                'prizes'   => $showPrizeInfos,
//                'paginate' => $prizeInfos,
//                'limit'    => $limit,
//                'offset'   => $offset,
//            ]
//        );
        return $this->respondJson([
            'data'=>[
                'prizes'   => $showPrizeInfos,
                'paginate' => $prizeInfos,
                'limit'    => $limit,
                'offset'   => $offset,
            ]
        ]);
    }

    /**
     * 按条件查询奖品信息
     *
     * @param Request           $request 查询条件数组，数据key为prizes表的字段名
     * @param PrizeModelService $prizeModelService
     * @param StorageService    $storageService
     * @param UserService       $userService
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function queryPrizes(Request $request, PrizeModelService $prizeModelService,
                                StorageService $storageService, UserService $userService)
    {
        $requestData = $request->query->get('data', '');
        if (!$requestData) {
            $requestData = $request->query->all();
        } else {
            $requestData = json_decode($requestData, true);
        }
        $conditions = [
            'where'           => [],
            'whereNotIn'      => [],
            'whereIn'         => [],
            'orWhere'         => [],
            'whereNull'       => [],
            'whereNotNull'    => [],
            'whereBetween'    => [],
            'whereNotBetween' => [],
        ];
        if (!empty($requestData['search'])) {
            $conditions['where'][] = ['name', 'like', '%' . $requestData['search'] . '%'];
        }
        switch (@$requestData['category']) {
            case '1':
                $conditions['where'][] = ['type_code', '!=', PrizeType::ALIPAY];
                break;
            case '2':
                $conditions['where'][] = ['type_code', '!=', PrizeType::WECHAT];
                break;
        }
        if (!empty($requestData['exclude'])) {
            $prizeIds = explode(',', $requestData['exclude']);
            $conditions['whereNotIn'] = ['id', $prizeIds];
        }
        $userInfo = $userService->getLoginUser();
        $conditions['where'][] = ['user_id', $userInfo['id']];
        $conditions['where'][] = ['is_valid', Prize::IS_VALID_YES];
        $conditions['where'][] = ['group_code', $userInfo['groupcode']];
        $conditions['orWhere'][] = ['expired_end', '>', date('Y-m-d H:i:s')];
        $conditions['orWhere'][] = ['expired_end', null];
        $limit = @$requestData['limit'] ?: 10;
        $offset = @$requestData['offset'] ?: 0;
        $prizeInfos = $prizeModelService->getPaginateByConditions($conditions,
            ['prizeType', 'sponsor', 'activity', 'prizeRecord'], $limit, $offset);

        if ($prizeInfos) {
            $row = $prizeInfos['data'];
            foreach ($row as &$item) {
                $item['background_image'] = $storageService->tomedia($item['background_image']);
            }
            unset($item);
            $total = $prizeInfos['total'];

            return $this->respondJson(['rows' => $row, 'total' => $total]);
        } else {
            return $this->respondJson(['prizes' => [], 'code' => 1]);
        }
    }

    /**
     * 创建奖品，红包奖品创建订单，并返回订单ID
     *
     * @param Request           $request
     * @param PrizeAppService   $prizeAppService
     * @param PrizeModelService $prizeModelService
     * @param UserService       $userService
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function create(Request $request, PrizeAppService $prizeAppService, PrizeModelService $prizeModelService, UserService $userService)
    {

        $this->validate($request, [
            'data.prize.type_code'    => 'required|string|in:' . implode(',', [
                    PrizeType::ALIPAY, PrizeType::WECHAT,
                    PrizeType::ENTITY, PrizeType::COUPON, PrizeType::BUY]),
            'data.prize.resource'     => 'integer|in:' . implode(',', [Prize::BUILD_BY_CREATE, Prize::BUILD_BY_BUY]),
            'data.prize.name'         => 'required|string',
            'data.prize.stock_number' => ['numeric', 'regex:/^(([1-9][0-9]*)|(([0]\.\d{1,2}|[1-9][0-9]*\.\d{1,2})))$/'],
            'data.sponsor.name'       => 'array',
            'data.sponsor.logo'       => 'array',
            'data.sponsor.percent'    => 'array',
        ]);
        $requestData = $request->input('data', []);

        $user = app(UserService::class);
        $hasName = \App\Entities\Prize::query()
            ->where('name', Arr::get($requestData, 'prize.name'))
            ->where('group_code', $user->getGroupCode())
            ->exists();

        if ($hasName) {
            return $this->respondJson(['result' => '奖品已经存在', 'code' => 1]);
        }

        if (empty($requestData['prize']['background_image'])) {
            return $this->respondJson(['result' => '请上传奖品图片', 'code' => 1]);
        }

        if (empty($requestData['sponsor']['logo'][0])) {
            return $this->respondJson(['result' => '请上传商家LOGO', 'code' => 1]);
        }

        if (PrizeType::COUPON == Arr::get($requestData, 'prize.type_code')) {
            $exchangeMethod = Arr::get($requestData, 'prize.exchange_method');
            if (0 == $exchangeMethod) {
                if (!Str::startsWith(Arr::get($requestData, 'prize.exchange_url'), ['http://', 'https://'])) {
                    return $this->respondJson(['result' => '兑奖地址必须使用http://或https://开头', 'code' => 1]);
                }
            }

            $extends = $request->input('fields', []);
            Arr::set($requestData, 'prize.extends', json_encode($extends));

            Arr::set($requestData, 'prize.stock_number', 0);
        }

        if (!isset($requestData['prize']['extends'])) {
            Arr::set($requestData, 'prize.extends', '[]');
        }

        $userInfo = $userService->getLoginUser();
        $conditions['group_code'] = $userInfo['groupcode'];
        $conditions['name'] = Arr::get($requestData, 'prize.name');
        $result = $prizeModelService->getPrizeByConditions($conditions, []);
        if ($result) {
            return $this->respondJson(['result' => '奖品名称重复', 'code' => 1]);
        }

        $prizeInfo = $prizeAppService->analyzeCreateInfo($requestData);
        $result = $prizeModelService->create($prizeInfo);
        if ($result) {
            $prizeInfo['prize']['id'] = $result['id'];

            if (PrizeType::ENTITY == Arr::get($requestData, 'prize.type_code')) {
                if ($id = Arr::get($result, 'id')) {
                    event(new EntityPrizeCreated($id, Arr::get($requestData, 'prize.stock_number')));
                }
            }

            if (in_array($requestData['prize']['type_code'], [PrizeType::BUY, PrizeType::ALIPAY, PrizeType::WECHAT])) {
                $orderInfo = $prizeAppService->createOrder($prizeInfo);

                return $this->respondJson(
                    [
                        'result'  => $orderInfo['order']['order_id'],
                        'message' => '成功，请到列表页支付！',
                        'href'    => '/web/prize/index',
                    ]
                );
            } else {
                return $this->respondJson(['result' => '/web/prize/index']);
            }
        } else {
            return $this->respondJson(['result' => 'fail', 'code' => 1]);
        }
    }

    /**
     * 奖品入库
     *
     * @param Request            $request
     * @param PrizeRecordService $prizeRecordService
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function entry(Request $request, PrizeRecordService $prizeRecordService)
    {
        $number = $request->input('number');
        $id = $request->input('prize_id');
        $prizeRecords = $prizeRecordService->getByConditions(['prize_id' => $id])->toArray();
        $prizeRecordSummary = array_column($prizeRecords, 'summary', 'updated_at');
        ksort($prizeRecordSummary);
        $availableNumber = end($prizeRecordSummary);
        $prizeRecord = [
            'prize_id'   => $id,
            'number'     => $number,
            'summary'    => $availableNumber + $number,
            'created_at' => date('Y-m-d H:i:s'),
        ];
        $result = $prizeRecordService->create($prizeRecord);
        if ($result) {
            return $this->respondJson(['result' => '/web/prize/index']);
        } else {
            return $this->respondJson(['result' => 'fail', 'code' => 1]);
        }
    }

    /**
     * 奖品出库
     *
     * @param Request            $request
     * @param PrizeRecordService $prizeRecordService
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function delivery(Request $request, PrizeRecordService $prizeRecordService)
    {
        $number = $request->input('number');
        $id = $request->input('prize_id');
        $prizeRecords = $prizeRecordService->getByConditions(['prize_id' => $id])->toArray();
        $prizeRecordSummary = array_column($prizeRecords, 'summary', 'updated_at');
        ksort($prizeRecordSummary);
        $availableNumber = end($prizeRecordSummary);
        $prizeRecord = [
            'prize_id'   => $id,
            'number'     => $number,
            'summary'    => $availableNumber - $number,
            'operate'    => 'delivery',
            'created_at' => date('Y-m-d H:i:s'),
        ];
        $result = $prizeRecordService->create($prizeRecord);
        if ($result) {
            return $this->respondJson(['result' => '/web/prize/index']);
        } else {
            return $this->respondJson(['result' => 'fail', 'code' => 1]);
        }
    }

    /**
     * 奖品详情
     *
     * @param Request           $request
     * @param PrizeAppService   $prizeAppService
     * @param PrizeModelService $prizeModelService
     *
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
     */
    public function detail(Request $request, PrizeAppService $prizeAppService, PrizeModelService $prizeModelService)
    {
        $id = $request->get('prize_id');
        $prizeInfo = $prizeModelService->getPrizeById($id);
        $prizeRecords = $prizeAppService->analyzePrizeRecord($prizeInfo);

        return view('web.prize.detailPrize', $prizeRecords);
    }

    /**
     * 可用奖品数
     *
     * @param Request           $request
     * @param PrizeModelService $prizeModelService
     *
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\JsonResponse|\Illuminate\View\View
     */
    public function availablePrize(Request $request, PrizeAppService $prizeAppService,
                                   PrizeModelService $prizeModelService)
    {
        $id = $request->get('prize_id');
        $conditions = $prizeAppService->prepareQueryConditiond(['id' => $id]);
        $limit = $request->get('limit', 1);
        $offset = $request->get('offset', 0);
        $prizeInfos = $prizeModelService->getPrizeByConditions($conditions,
            ['prizeType', 'sponsor', 'activity', 'prizeRecord', 'prizePayment'], $limit, $offset);
        $prizeInfoArray = $prizeInfos->toArray();
        $showPrizeInfos = $prizeAppService->analyzePrizeInfo($prizeInfoArray);

        foreach ($showPrizeInfos as $item) {
            $availableNumber = $item['availableNumber'];
        }

        return $this->respondJson(['availableNumber' => $availableNumber]);
    }

    /**
     * 编辑优惠券、实物奖品信息
     *
     * @param Request           $request
     * @param PrizeAppService   $prizeAppService
     * @param PrizeModelService $prizeModelService
     *
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\JsonResponse|\Illuminate\View\View
     */
    public function modify(Request $request, PrizeAppService $prizeAppService, PrizeModelService $prizeModelService)
    {
        if ($request->isMethod('get')) {
            $prizeId = $request->query->get('prize_id');
            $prizeInfo = $prizeModelService->getPrizeById($prizeId);

            try {
                $prizeInfo['extends'] = json_decode(Arr::get($prizeInfo, 'extends'), true);
            } catch (\Throwable $t) {
                $prizeInfo['extends'] = [];
            }

            return view('web.prize.modify' . ucfirst($prizeInfo['type_code']), compact('prizeInfo'));
        } else {
            $prizeInfo = $request->input('data', []);

            if (!isset($prizeInfo['sponsor'])) {
                return $this->respondJson(['result' => '请添加供应商', 'code' => 1]);
            }

            $prizeInfo = $prizeAppService->analyzeModifyInfo($prizeInfo);
            if (!Arr::get($prizeInfo, 'prize.background_image')) {
                return $this->respondJson(['result' => '请上传奖品图片', 'code' => 1]);
            }
            if (!Arr::get($prizeInfo, 'sponsor.0.logo')) {
                return $this->respondJson(['result' => '请上传商家LOGO', 'code' => 1]);
            }
            $exchangeMethod = Arr::get($prizeInfo, 'prize.exchange_method');
            if ($exchangeMethod == Prize::NO_VOUCHER && Arr::get($prizeInfo, 'prize.exchange_url')) {
                if (!Str::startsWith(Arr::get($prizeInfo, 'prize.exchange_url'), ['http://', 'https://'])) {
                    return $this->respondJson(['result' => '兑奖地址必须使用http://或https://开头', 'code' => 1]);
                }
            }
            $extends = $request->input('fields', []);
            Arr::set($prizeInfo, 'prize.extends', json_encode($extends));
            $result = $prizeModelService->modify($prizeInfo, ['id' => $prizeInfo['prize']['id']]);
            if ($result) {
                return $this->respondJson(['result' => '/web/prize/index']);
            } else {
                return $this->respondJson(['result' => 'fail', 'code' => 1]);
            }
        }
    }

    /**
     * 删除奖品
     *
     * @param Request             $request
     * @param PrizeModelService   $prizeService
     * @param PrizePaymentService $prizePaymentService
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function delete(Request $request, PrizeModelService $prizeService,
                           PrizePaymentService $prizePaymentService, ActivityPrizeService $activityPrizeService)
    {
        $prizeId = $request->input('prize_id');
        $count = $activityPrizeService->findOneByPrizeID($prizeId);
        if ($count) {
            return $this->respondJson(['result' => '奖品已绑定活动，不可删除', 'code' => 1]);
        }
        $result = $prizeService->delete(['id' => $prizeId], false);
        if ($result) {
            $prizePaymentService->delete(['prize_id' => $prizeId]);

            return $this->respondJson(['result' => '/web/prize/index']);
        }

        return $this->respondJson(['result' => '删除奖品操作失败', 'code' => 1]);
    }

    /**
     * 检查奖品名称是否已存在
     *
     * @param string            $prize_id
     * @param Request           $request
     * @param PrizeModelService $prizeService
     * @param UserService       $userService
     *
     * @return string
     */
    public function checkName($prize_id = '', Request $request,
                              PrizeModelService $prizeService, UserService $userService)
    {
        $userInfo = $userService->getLoginUser();
        $aconditions['group_code'] = $userInfo['groupcode'];
        $aconditions['name'] = $request->input('param');
        $result = $prizeService->getPrizeByConditions($aconditions, []);
        if ($result) {
            if ($prize_id != '') {
                $prizeInfo = reset($result);
                if ($prizeInfo['id'] == $prize_id) {
                    return 'y';
                } else {
                    return '奖品名称重复';
                }
            } else {
                return '奖品名称重复!';
            }
        } else {
            return 'y';
        }
    }

    /**
     * 上传文件到temp区
     *
     * @param Request        $request
     * @param StorageService $storageService
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function upload(Request $request, StorageService $storageService)
    {
        $files = $request->files->all();
        try {
            $logoImages = $storageService->storeAsTmpImage($files['upfile'], ['ext' => 'csv']);
            return $this->respondJson(['result' => $logoImages['url']]);
        } catch (\Exception $e) {
            return $this->respondJson(['result' => $e->getMessage(), 'code' => 1]);
        }
    }

    public function showImportVoucherCodePage($id)
    {
        return view('web.prize.import-voucher-code', compact('id'));
    }
}
